package com.github.framework.webmvc.servlet;

import com.github.framework.annotaion.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @program: springv2
 * @description: 用于将一个handlerMapping对象适配成一个ModelAndView
 * @author: Pop
 * @create: 2021-06-26 22:06
 **/
public class HandlerAdapter {


    public ModelAndView handler(HttpServletRequest req, HttpServletResponse resp, HandlerMapping handlerMapping) throws  Exception {

        // 保存形参列表，用于后面调用
        Map<String,Integer> param = new HashMap<String,Integer>();

        Annotation[] [] pa = handlerMapping.getMethod().getParameterAnnotations();
        for (int j = 0; j < pa.length ; j ++) {
            for(Annotation a : pa[j]){
                if(a instanceof RequestParam){
                    String paramName = ((RequestParam) a).value();
                    if(!"".equals(paramName.trim())){
                        //保存被 加上了RequestParam的参数的名字和参数类型
                        param.put(paramName,j);
                    }
                }
            }
        }
        Method method=handlerMapping.getMethod();
        //获得形参列表
        Class<?> [] parameterTypes = method.getParameterTypes();
        // 一些特殊的参数，例如HttpServletRequest 和 HttpServletResponse
        for (int i = 0; i <parameterTypes.length ; i++) {
            Class<?> clazz = parameterTypes[i];
            if(clazz == HttpServletRequest.class||clazz == HttpServletResponse.class)
            {
                param.put(clazz.getName(),i);
            }
        }
        // http://localhost:8080/query?name=pop&pipi
        Map<String,String[]> params = req.getParameterMap();
        Object[] paramList = new Object[parameterTypes.length];
        // 根据request传过来的值对paramList进行初始化
        for (Map.Entry<String,String[]> entry : params.entrySet()) {
           //将数组替换成字符串串，并且转型
            String value=Arrays.toString(entry.getValue()).
                    replaceAll("\\[|\\]","")
                    .replaceAll("\\s+","");//去掉多余的空格
            if(!param.containsKey(entry.getKey())){
                //说明没有传这个值
                continue;
            }
            int index = param.get(entry.getKey());
            //可能会有多种类型需要强制转换
            paramList[index] = caseStringValue(value,parameterTypes[index]);
        }

        //当然，如果SpringMvc是如果你在的Controller方法里写了request和response是会自动赋值的
        //所以我们这里也需要做一个判断
        if(param.containsKey(HttpServletRequest.class.getName()))
        {
            int index = param.get(HttpServletRequest.class.getName());
            //可能会有多种类型需要强制转换
            paramList[index] = req;
        }

        if(param.containsKey(HttpServletResponse.class.getName()))
        {
            int index = param.get(HttpServletResponse.class.getName());
            //可能会有多种类型需要强制转换
            paramList[index] = resp;
        }

        Object result = method.invoke(handlerMapping.getController(),paramList);

        //一种如果是null或者是void
        if(result==null||result instanceof Void )
        {
            return null;
        }
        //当然这里如果加了@ResponseBody的话还会返回json之类的

        //是否是返回值是ModelAndView
        boolean isModelAndView = method.getReturnType() == ModelAndView.class;
        if(isModelAndView)
        {
            return (ModelAndView) result;
        }

        return null;
    }

    private Object caseStringValue(String value, Class<?> parameterType) {
        if(String.class == parameterType)
        {
            return value;
        }else if(Integer.class == parameterType)
        {
            return Integer.valueOf(value);
        }else if(Double.class == parameterType)
        {
            return Double.valueOf(value);
        }
        return value;
    }
}
